home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-07-09 | 16.5 KB | 758 lines | [TEXT/CWIE] |
- // MSFile.c
- //
- // Original version by Jon Lansdell and Nigel Humphreys.
- // 4.0 and 3.1 updates by Greg Sutton.
- // ©Apple Computer Inc 1996, all rights reserved.
-
- /*
- Changes for 4.0
-
- 28-Feb-96 : GS : Added script to document file. This script is attached to the document
- and gets first go at handling Apple events targetted at the document.
- */
-
- #include <Errors.h>
- #include <Resources.h>
- #include <Desk.h>
- #ifdef THINK_C
- #include "PLStrs.h"
- #else
- #include <PLStringFuncs.h>
- #endif
- #include <AppleEvents.h>
- #include <AERegistry.h>
- #include <StandardFile.h>
- #include "MSFile.h"
- #include "Offscreen.h"
- #include "MSResultWind.h"
- #include "MSAEWindowUtils.h"
- #include "MSScript.h"
- #include "MSAESetData.h"
-
- #include <LowMem.h>
-
- // Constants
- const OSType kStyleInfoType = 'TFSF';
- const OSType kHeaderInfoType = 'TFSS';
- const OSType kGXPrinterInfoType = 'TFGX';
-
-
- // Name: FileError
- // Purpose: Puts up an error alert.
-
- #pragma segment File
-
- void FileError( Str255 s, Str255 f )
- {
- short alertResult;
-
- SetCursor(&qd.arrow);
- ParamText(s, f, (unsigned char *)"", (unsigned char *)"");
- alertResult = Alert( ErrorAlert, NULL );
- }
-
- // Name: DoClose
- // Purpose: Closes a window.
-
- #pragma segment File
-
- OSErr DoClose( WindowPtr aWindow,Boolean canInteract,DescType dialogAnswer )
- {
- DPtr aDocument;
- short alertResult;
- OSErr myErr;
-
- myErr = noErr;
-
- aDocument = DPtrFromWindowPtr(aWindow);
- if ( ! aDocument )
- return noErr;
-
- // Save if the windows contents have changed and it's not the results window
- if ((aDocument->dirty) && !IsThisResultWind(aWindow))
- {
- if (canInteract && (dialogAnswer==kAEAsk))
- {
- alertResult = DoFileDialog ( kSaveDontsaveDialog, aWindow );
- switch ( alertResult )
- {
- case kStdOkItemIndex:
- if (aDocument->everSaved == false)
- {
- myErr = GetFileNameToSaveAs(aDocument);
- if (myErr == noErr)
- myErr = DoSave(aDocument, aDocument->theFSSpec);
- }
- else
- myErr = SaveUsingTemp(aDocument);
- break;
-
- case kStdCancelItemIndex:
- return(userCanceledErr);
- break;
-
- case kDontSaveItemIndex:
- aDocument->dirty = false;
- break;
- }
- }
- else
- {
- if (dialogAnswer==kAEYes)
- if (aDocument->everSaved == false)
- {
- if (canInteract)
- {
- myErr = GetFileNameToSaveAs(aDocument);
- if (myErr==noErr)
- myErr = DoSave(aDocument, aDocument->theFSSpec);
- }
- else
- return(errAENoUserInteraction);
- }
- else
- myErr = SaveUsingTemp(aDocument);
- else
- myErr = noErr; // Don't save
- }
- }
-
- if ( myErr == noErr )
- CloseMyWindow(aWindow);
-
- return(myErr);
- }
-
-
- // This is called to display the "save before closing" and "revert" dialogs.
-
- short DoFileDialog( short theDlogID, WindowRef theWindow )
- {
- short theItem;
- DialogRef theDialog;
- WindowRef dialogWindow;
- DPtr theDocument;
- Str255 theTitle, theReason;
-
-
- theDocument = DPtrFromWindowPtr ( theWindow );
-
- theDialog = GetNewDialog ( theDlogID, nil, (WindowRef) -1 );
- dialogWindow = GetDialogWindow ( theDialog );
- SetPortWindowPort ( dialogWindow );
-
-
- if ( theDocument->everSaved == false )
- GetWTitle ( theWindow, theTitle ); // Pick it up as a script may have changed it
- else
- PLstrcpy ( theTitle, theDocument->theFileName );
-
- if ( gQuitting )
- GetIndString ( theReason, kMiscStrings, kQuittingIndex );
- else
- GetIndString ( theReason, kMiscStrings, kClosingindex );
-
- SetCursor ( &qd.arrow );
- ParamText ( theTitle, theReason, nil, nil );
- ShowMSWindow ( dialogWindow );
- SelectWindow ( dialogWindow );
-
- SetDialogDefaultItem ( theDialog, kStdOkItemIndex );
- SetDialogCancelItem ( theDialog, kStdCancelItemIndex );
-
- // As long as the only enabled items are the dimissers,
- // there is no need to call ModalDialog within a loop.
- ModalDialog ( nil, &theItem );
- DisposeDialog ( theDialog );
-
- return theItem;
- }
-
-
- #pragma segment File
-
- // DoQuit
- // saveOpt - one of kAEAsk,kAEYes,kAENo
- // if kAEYes or kAEAsk then AEInteactWithUser should have been called
- // before DoQuit. Assumes that it can interact if it needs to.
-
- void DoQuit( DescType saveOpt )
- {
- WindowPtr aWindow;
- WindowPtr nextWindow;
- WindowPeek nextWPeek;
- short theKind;
- OSErr check;
-
- aWindow = (WindowPtr)LMGetWindowList();
-
- gQuitting = true;
- while ( aWindow )
- {
- nextWPeek = ((WindowPeek)aWindow)->nextWindow;
- nextWindow = &nextWPeek->port;
- if (Ours(aWindow))
- {
- check = DoClose(aWindow, true, saveOpt);
- if ( check != noErr )
- {
- gQuitting = false;
- return;
- }
- }
- else
- {
- theKind = ((WindowPeek)aWindow)->windowKind;
- if (theKind < 0)
- CloseDeskAcc(theKind);
- }
- aWindow = nextWindow;
- }
- } // DoQuit
-
-
- OSErr GetFile( FSSpec *theFSSpec )
- {
- SFTypeList myTypes;
- StandardFileReply reply;
-
- myTypes[0] = 'TEXT';
-
- StandardGetFile( NULL, 1, myTypes, &reply );
-
- if (reply.sfGood)
- {
- *theFSSpec = reply.sfFile;
- return(noErr);
- }
- else
- return(userCanceledErr);
- }
-
-
- #pragma segment File
-
- OSErr DoCreate( FSSpec theSpec )
- {
- OSErr err;
-
- err = FSpCreate(&theSpec, MenuScripterAppSig, 'TEXT', smSystemScript);
-
- if (err != noErr)
- ShowError((unsigned char *)"\pDoCreate", err);
-
- return(err);
- }
-
-
- #pragma segment File
-
- OSErr WriteFile( DPtr theDocument, short refNum, FSSpec theFSSpec )
- {
- short resFile;
- long length;
- HHandle theHHandle;
- StScrpHandle theSHandle;
- OSErr err;
- StringHandle theAppName;
- short oldSelStart;
- short oldSelEnd;
- Handle thePHandle;
- Handle myText;
- Handle thePGXHandle;
-
- tWindowOffscreen* theOffscreen = nil;
-
- // first write out the text to the data fork
-
- length = (*(theDocument->theText))->teLength;
- myText = (*(theDocument->theText))->hText;
-
- HLock( myText );
-
- err = FSWrite(refNum, &length, *myText);
- if ( noErr != err )
- return err;
-
- HUnlock( myText );
-
- // we are writing to a temporary file, so we need to create the resource file
- // before writing out the resources
- // now open the resource file
-
- HCreateResFile(theFSSpec.vRefNum, theFSSpec.parID, theFSSpec.name);
- err = ResError();
- if (err)
- {
- ShowError((unsigned char *)"\pHCreateResFile", err);
- return(err);
- }
-
- resFile = HOpenResFile( theFSSpec.vRefNum, theFSSpec.parID, theFSSpec.name, fsWrPerm );
- err = ResError();
-
- if (err)
- {
- ShowError((unsigned char *)"\pHOpenResFile", err);
- return(err);
- }
-
- // Write out our 'TFSF' resource to file
-
- // Draw everything into offscreen pixmap.
- theOffscreen = DrawOffscreen ( theDocument->theWindow );
- if ( theOffscreen )
- (*theDocument->theText)->inPort = (GrafPtr) theOffscreen->offscreenWorld;
-
-
- oldSelStart = (*(theDocument->theText))->selStart;
- oldSelEnd = (*(theDocument->theText))->selEnd;
- TESetSelect( 0, kMaxTELength, theDocument->theText );
-
- theSHandle = TEGetStyleScrapHandle(theDocument->theText);
-
- TESetSelect(oldSelStart,oldSelEnd, theDocument->theText);
-
-
- if ( theOffscreen )
- {
- // If it wasn't for the caret, we wouldn't need to draw this
- theOffscreen = DrawOnscreen ( theOffscreen );
- (*theDocument->theText)->inPort = theDocument->theWindow;
- }
-
- AddResource((Handle)theSHandle, kStyleInfoType, 255, (unsigned char *)"\pStyle Info");
- err = ResError();
- if (err)
- {
- ShowError((unsigned char *)"\pAddResource - Style Info", err);
- return(err);
- }
-
- // Write out the printer info
-
- // First the QD info
-
- if (theDocument->thePrintSetup)
- {
- thePHandle = (Handle)theDocument->thePrintSetup;
- err = HandToHand(&thePHandle);
-
- AddResource(thePHandle, 'TFSP', 255, (unsigned char *)"\pPrinter Info");
- err = ResError();
- if (err)
- {
- ShowError((unsigned char *)"\pAddResource- TFSP", err);
- return(err);
- }
- }
-
- // Next the QD QX info
- if ( ( gGXIsPresent ) && ( theDocument->documentJob ) )
- {
- thePGXHandle = NewHandle(0);
- GXFlattenJobToHdl(theDocument->documentJob, thePGXHandle);
-
- AddResource(thePGXHandle, kGXPrinterInfoType, 255, (unsigned char *)"\pGX Printer Info");
- err = ResError();
- if (err)
- {
- ShowError((unsigned char *)"\pAddResource- TFGX", err);
- return(err);
- }
- }
-
- theHHandle = (HHandle)NewHandle(sizeof(HeaderRec));
- HLock((Handle)theHHandle);
-
- GetFontName(theDocument->theFont, (unsigned char *)&(*theHHandle)->theFont);
- (*theHHandle)->theSize = theDocument->theSize;
- (*theHHandle)->theStyle = theDocument->theStyle;
- (*theHHandle)->lastID = 0;
-
- HUnlock((Handle)theHHandle);
-
- AddResource((Handle)theHHandle, kHeaderInfoType, 255, (unsigned char *)"\pHeader Info");
-
- err = ResError();
- if (err)
- {
- ShowError((unsigned char *)"\pAddResource- Header Info", err);
- return(err);
- }
-
- // Now put an AppName in for Finder in 7.0
-
- theAppName = (StringHandle)NewHandle(gAppRec.theName[0]);
- PLstrcpy( *theAppName, gAppRec.theName );
-
- AddResource((Handle)theAppName, 'STR ', -16396, (unsigned char *)"\pFinder App Info");
-
- err = ResError();
-
- if (err)
- {
- ShowError((unsigned char *)"\pAppName", err);
- return(err);
- }
-
- // Each document has a script associated with it
- // this can be changed so store in resource.
- err = StoreDocumentScript( theDocument, resFile );
-
- CloseResFile( resFile );
-
- return err;
- } // WriteFile
-
-
- #pragma segment File
-
- OSErr ReadFile( DPtr theDocument, short refNum, Str255 fn )
- {
- long theSize;
- short resFile;
- OSErr err;
- HHandle aHandle;
- Handle gHandle;
- Handle hGXJobData;
- Boolean gotQDPrintRec;
-
- gotQDPrintRec = false;
-
- err = GetEOF(refNum, &theSize);
- if (err)
- return(err);
-
- // We're only using TE, so check that there is not more than 32K worth of text
-
- if (theSize > kMaxTELength)
- return(1);
-
- gHandle = NewHandle(theSize);
- HLock(gHandle);
- err = FSRead(refNum, &theSize, *gHandle);
-
- if (err)
- {
- HUnlock(gHandle);
- return(err);
- }
-
- resFile = HOpenResFile(theDocument->theFSSpec.vRefNum,
- theDocument->theFSSpec.parID,
- fn,
- fsWrPerm);
- if ( resFile == -1 )
- err = fnfErr;
-
- if ( err == noErr )
- {
- aHandle = NULL;
-
- if ( Count1Resources( kHeaderInfoType ) )
- aHandle = (HHandle)Get1Resource( kHeaderInfoType, 255 );
-
- // New Format Info
-
- aHandle = nil;
-
- if ( Count1Resources( kStyleInfoType ) )
- aHandle = (HHandle)Get1Resource( kStyleInfoType, 255 );
-
- HLock(gHandle);
- TEStylInsert( *gHandle, GetHandleSize(gHandle),
- (StScrpHandle)aHandle, theDocument->theText );
- HUnlock(gHandle);
-
- // If there is a print record saved, ditch the old one
- // created by new document and fill this one in
-
- if (Count1Resources('TFSP'))
- {
- if (theDocument->thePrintSetup)
- DisposHandle((Handle)theDocument->thePrintSetup);
-
- theDocument->thePrintSetup = (THPrint)Get1Resource('TFSP', 255);
- err = HandToHand((Handle *)&theDocument->thePrintSetup);
-
- gotQDPrintRec = true;
- if (! gGXIsPresent)
- PrValidate(theDocument->thePrintSetup);
- }
-
- if ( gGXIsPresent )
- if ( Count1Resources( kGXPrinterInfoType ) )
- {
- if (theDocument->documentJob)
- {
- // GXDisposeJob(theDocument->documentJob);
- // theDocument->documentJob = nil;
- }
-
- hGXJobData = Get1Resource( kGXPrinterInfoType, 255 );
-
- if (hGXJobData)
- {
- GXUnflattenJobFromHdl(theDocument->documentJob, hGXJobData);
- err = GXGetJobError(theDocument->documentJob);
- ReleaseResource(hGXJobData);
- }
- }
- else
- {
- if (gotQDPrintRec)
- GXConvertPrintRecord(theDocument->documentJob, theDocument->thePrintSetup);
- }
-
- err = LoadDocumentScript( theDocument, resFile );
-
- CloseResFile(resFile);
-
- err = ResError();
- if (err)
- {
- ShowError((unsigned char *)"\pReadFile - CloseResFile", err);
- return(err);
- }
- }
- else
- TESetText( *gHandle, GetHandleSize(gHandle), theDocument->theText );
-
- if (gHandle)
- DisposHandle(gHandle);
-
- if (err==fnfErr)
- err = noErr;
-
- return(err);
- } // ReadFile
-
-
- // Name: GetFileContents
- // Purpose: Opens the document specified by theFSSpec and puts
- // the contents into theDocument.
-
- #pragma segment File
-
- OSErr GetFileContents( FSSpec theFSSpec, DPtr theDocument )
- {
- OSErr err;
- short theRefNum;
-
- // this can be called from two places- on an OpenDoc AppleEvent
- // and by the user just selecting Open from the File Menu
- // assume that the CFS is correct when the routine is called
-
- err = FSpOpenDF( &theFSSpec, fsRdWrPerm, &theRefNum );
- if (err)
- {
- ShowError((unsigned char *)"\pFSpOpenDF", err);
- return(err);
- }
- else
- {
- err = ReadFile(theDocument, theRefNum, theFSSpec.name);
- if (err)
- {
- ShowError((unsigned char *)"\pReadFile", err);
- return(err);
- }
- err=FSClose(theRefNum);
- if (err)
- {
- ShowError((unsigned char *)"\pFSClose", err);
- return(err);
- }
- return(noErr);
- }
- }
-
-
- #pragma segment File
-
- OSErr SaveUsingTemp( DPtr theDocument )
- {
- Str255 tempName;
- FSSpec tempFSSpec;
- OSErr err;
-
- // save the file to disk using a temporary file
- // this is the recommended way of doing things
- // first write out the file to disk using a temporary filename
- // if it is sucessfully written, exchange the temporary file with the last one saved
- // then delete the temporary file- so if anything goes wrong, the original version is still there
- // first generate the temporary filename
-
- GetTempFileName(theDocument, tempName);
-
- //create this file on disk
-
- tempFSSpec = theDocument->theFSSpec;
- PLstrcpy( tempFSSpec.name, tempName );
-
- err = DoCreate(tempFSSpec);
-
- // now save the file as normal
-
- if (err == noErr)
- err = DoSave(theDocument, tempFSSpec);
-
- if (err == noErr)
- err = FSpExchangeFiles(&tempFSSpec, &theDocument->theFSSpec);
-
- // we've exchanged the files, now delete the temporary one
-
- if (err == noErr)
- err = FSpDelete(&tempFSSpec);
-
- return(err);
- }
-
-
- #pragma segment File
-
- // Fills in the document record with the user chosen destination
-
- OSErr GetFileNameToSaveAs(DPtr theDocument)
- {
- StandardFileReply reply;
- OSErr err;
- Str255 suggestName;
-
- GetWTitle(theDocument->theWindow, suggestName);
-
- StandardPutFile((unsigned char *)"\pSave Document As:", suggestName, &reply);
-
- if (reply.sfGood)
- {
- err = FSpDelete(&reply.sfFile);
-
- if (!((err==noErr) || (err==fnfErr)))
- return(err);
- else
- err = noErr;
-
- theDocument->theFSSpec = reply.sfFile;
- PLstrcpy(theDocument->theFileName, reply.sfFile.name);
- }
- else
- err = userCanceledErr;
-
- return(err);
- } // GetFileNameToSaveAs
-
-
- #pragma segment File
-
- OSErr DoSave( DPtr theDocument, FSSpec theFSSpec )
- {
- short refNum;
- OSErr fileErr;
-
- fileErr = FSpOpenDF(&theFSSpec, fsRdWrPerm, &refNum);
-
- if (fileErr == fnfErr)
- {
- fileErr = DoCreate(theFSSpec);
-
- if (fileErr)
- return(fileErr);
-
- fileErr = FSpOpenDF(&theFSSpec, fsRdWrPerm, &refNum);
- }
-
- if (fileErr == noErr)
- {
- fileErr = WriteFile(theDocument, refNum, theFSSpec);
-
- if (fileErr==noErr)
- theDocument->dirty = false;
-
- fileErr = FSClose(refNum);
- }
- else
- FileError((unsigned char *)"\perror opening file ", theFSSpec.name);
-
- return(fileErr);
- }
-
-
- #pragma segment File
-
- OSErr OpenOld( FSSpec aFSSpec )
- {
- DPtr aDocument;
- AEDesc aDesc = { typeNull, NULL },
- aBoundsDesc = { typeNull, NULL };
- WindowPropToken aPropToken;
- Str255 aPStr;
- OSErr anErr;
-
- aDocument = NewDocument( true, (WindowPtr)-1L );
-
- SetWTitle( aDocument->theWindow, aFSSpec.name );
-
- SetPort( aDocument->theWindow );
-
- aDocument->theFSSpec = aFSSpec;
-
- PLstrcpy( aDocument->theFileName,aFSSpec.name );
-
- aDocument->dirty = false;
- aDocument->everSaved = true;
-
- anErr = GetFileContents( aFSSpec, aDocument );
-
- if ( noErr == anErr )
- { // Try and get the saved script property
- if ( kOSANullScript != aDocument->theScriptID )
- {
- PLstrcpy( aPStr, "\pwindowbounds" );
- anErr = AECreateDesc( typeChar, (Ptr)&aPStr[1], aPStr[0], &aDesc );
- if ( noErr != anErr ) goto done;
-
- anErr = GetScriptProperty( aDocument->theScriptID, &aDesc, &aBoundsDesc );
- if ( noErr == anErr )
- { // Set up a token for the document
- aPropToken.tokenWindowToken.tokenWindow = aDocument->theWindow;
- aPropToken.tokenProperty = pBounds;
-
- anErr = SetDocumentTokenProperty( &aPropToken, &aBoundsDesc );
- }
- else
- anErr = noErr; // Script does not have this property
- }
-
- ResizeWindow( aDocument );
- SelectWindow( aDocument->theWindow );
- ShowMSWindow( aDocument->theWindow );
- }
- else
- FileError( (unsigned char *)"\pError Opening ", aFSSpec.name );
-
- done:
- (void)AEDisposeDesc( &aDesc );
- (void)AEDisposeDesc( &aBoundsDesc );
-
- return anErr;
- } // OpenOld
-
- /*
- #pragma segment File
-
- OSErr OpenUsingAlias( AliasHandle theAliasH )
- {
- OSErr err;
- FSSpec aFSSpec;
- Boolean dummy;
-
- err = ResolveAlias(nil, theAliasH, &aFSSpec, &dummy);
-
- if (err == noErr)
- err = OpenOld(aFSSpec);
-
- return(err);
- }
- */
-